#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include"Defines.cpp"

class Server
{
    private:
    uint16_t _serverPort;
    int _serverSocket;
    public:
    struct ClientData
    {
        public:
        sockaddr_in ClientAddr;
        int ClientSock;
    };
    
    bool InitServer(uint16_t *port)
    {
        _serverPort = *port;
        //创建套接字
        _serverSocket = socket(PF_INET, SOCK_STREAM, 0);
        if(-1 == _serverSocket)
        {
            PrintLine("套接字创建失败");
            return false;
        }
        //设置套接字端口可复用性
        int opt = 1;
        int ret = setsockopt(_serverSocket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
        if(-1 == ret)
        {
            PrintLine("设置端口可复用属性失败");
            return false;
        }
        //配置服务器的网络地址的属性192.168.1.1
        sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(_serverPort);//主机字节顺序转变成网络字节顺序，host to network short
        serverAddr.sin_addr.s_addr = INADDR_ANY;
        //绑定套接字和网络地址属性
        ret = bind(_serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr));
        if(ret < 0)
        {
            PrintLine("套接字绑定失败");
            return false;
        }
        //如果传入端端口为0，随机分配一个端口
        if(0 == *port)
        {
            int length = sizeof(serverAddr);
            ret = getsockname(_serverSocket, (sockaddr*)&serverAddr, (socklen_t*)&length);
            if(ret < 0)
            {
                PrintLine("随机分配端口失败");
                return false;
            }
            _serverPort = ntohs(serverAddr.sin_port);
            *port = _serverPort;
        }
        return true;
    }

    bool Listen(int queueLength)
    {
        return listen(_serverSocket, queueLength) == 0;
    }

    bool Accept(ClientData *clientData)
    {
        int length = sizeof(clientData->ClientAddr);
        clientData->ClientSock = accept(_serverSocket, (sockaddr*)&(clientData->ClientAddr), (socklen_t*)&length);
        return clientData->ClientSock != -1;
    }

    uint16_t GetServerPort()
    {
        return _serverPort;
    }

    int GetServerSocket()
    {
        return _serverSocket;
    }
};